package com.tan.chowder.login.config;

import com.alibaba.fastjson.JSON;
import com.tan.chowder.login.service.impl.JwtServiceImpl;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;

/**
 * JwtAuthenticationFilter
 *
 * @author chenx
 */
@Component
@RequiredArgsConstructor

public class JwtAuthenticationFilter extends OncePerRequestFilter {
    @Resource
    private JwtServiceImpl jwtServiceImpl;
    @Resource
    private RedisTemplate<String, String> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        System.out.println(" =======拦截器启动===== ");
        System.out.printf(" =======拦截器路径%s===== %n", request.getRequestURL().toString());
        // 从HttpServletRequest请求中获取"Authorization"头部的值
        String token = request.getHeader("Authorization");
        // 判断token是否不为null，并且以"Bearer "开头
        if (token != null && token.startsWith("Bearer ")) {
            // 将token从"Bearer "开头截取
            token = token.substring(7);
            String username = jwtServiceImpl.getUsernameFromToken(token);
            String redisKey = jwtServiceImpl.generateUserRedisKey(username, token);
            String redisUser = redisTemplate.opsForValue().get(redisKey);
            if (jwtServiceImpl.isTokenValid(token) && StringUtils.hasText(redisUser)) {
                //没有用户信息，就需要从数据库中获取用户信息
                //有效的token
                System.out.println("=====有效的token = " + token);
                // 创建UsernamePasswordAuthenticationToken类型的authentication
                //将用户信息存放在SecurityContextHolder.getContext()，后面的过滤器就可以获得用户信息了。这表明当前这个用户是登录过的，后续的拦截器就不用再拦截了
                UserDetails userDetails = JSON.parseObject(redisUser, UserDetails.class);
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, new ArrayList<>());
                // 将authentication设置到当前SecurityContextHolder中的Authentication
                SecurityContextHolder.getContext().setAuthentication(authentication);
                //刷新token,结合自身系统场景而定：相当于每次访问都进行续命
                refreshToken(token);
            } else {
                System.err.println("===无效token===");
            }
        }
        // 执行过滤器链中的下一个过滤器
        chain.doFilter(request, response);
    }

    /**
     * 刷新token
     */
    private void refreshToken(String token) {
        jwtServiceImpl.generateRefreshToken(token);
    }
}
